// @ts-ignore
import React, {useEffect, useState} from 'react'
/** 图核心组件 & 类型定义 */
import type { IAppLoad, NsGraph, IApplication, NsGraphCmd } from '@antv/xflow'
import {XFlow, XFlowCanvas, createGraphConfig, XFlowGraphCommands, XFlowEdgeCommands, NsEdgeCmd} from '@antv/xflow'
import {Layout, Menu, MenuProps} from 'antd';

import type { NsNodeCmd } from '@antv/xflow'
import { XFlowNodeCommands } from '@antv/xflow'

import './ApprovalProcessDag.css'
import '@antv/xflow/dist/index.css'

import Graph from "echarts/types/src/data/Graph";
import {NodeContextMenu} from "./node-context-menu";
import UserModal from "./users-modal/userModal";
import {IAppConfigReady} from "_@antv_xflow-core@1.0.46@@antv/xflow-core/es/xflow-main/components";


export const useGraphConfig = createGraphConfig(config => {
  config.setX6Config({ grid: true })
  config.setNodeRender('NODE-START', props => {
    return <div className="react-node react-node-radius">{props.data?.info?.text}</div>
  })
  config.setNodeRender('NODE1', props => {
    return <div className="react-node">{props.data?.info?.text}</div>
  })
  config.setNodeTypeParser(node => node?.renderKey)
  config.setDefaultNodeRender(props => {
    return <div className="react-node"> {props.data.label} </div>
  })
})

let appRef: IApplication = undefined
const ApprovalProcessDag: React.FC<{}> = (props) => {
  const [graphData, setGraphData] = useState<NsGraph.IGraphData>(undefined)
  const [state, setState] = useState({currentNode: null, appRef: appRef, isModalVisible: false, isDisplay:false, currentUser:{}});
  const {userOptions, onNodeChange, nodes} = props
  const initNodes = nodes == null ? [] : nodes;
  //用户信息

  const onLoad: IAppLoad = async app => {
    appRef = app

    const nodes: NsGraph.INodeConfig[] = [
      { id: 'root', width: 150, height: 40, x: 100, y: 50, renderKey: 'NODE-START', info: { text: '审批开始' } },
    ]
    const edges: NsGraph.IEdgeConfig[] = [
    ]

    let i = 2;
    initNodes.forEach(item=>{
      //查询用户数据
      let user = {};
      userOptions.forEach(u=>{
        if(u.id == item.userId) {
          user = u
        }
      })
      //初始数据生成
      nodes.push(
        { id: item.userId, width: 150, height: 40, x: 170 * i, y: 50,renderKey: 'NODE1', info: { text: user.username } }
      )
      edges.push(
        {id:item.sourceUserId + "-" + item.userId, source:item.sourceUserId == 0 ? "root" : item.sourceUserId, target: item.userId}
      )
      i++
    })

    setGraphData({ nodes, edges })
    onNodeChange(initNodes)

    //处理点击事件
    const graphInstance: Graph = await app.getGraphInstance()
    graphInstance.on('node:click', async ({node}) => {
      const nodes = await app.getAllNodes()
      nodes.forEach(item=>{
        app.executeCommand<NsNodeCmd.HighlightNode.IArgs>(XFlowNodeCommands.HIGHLIGHT_NODE.id, {
          nodeId: item.id,
          stroke: null,
          strokeWidth: null,
        })
      })
      app.executeCommand<NsNodeCmd.HighlightNode.IArgs>(XFlowNodeCommands.HIGHLIGHT_NODE.id, {
        nodeId: node.id,
        stroke: '#f00',
        strokeWidth: 3,
      })

      setState({...state, currentNode: node, isDisplay: true})
    })

  }

  const onCreateNode = async (node, user) => {
    let nodeId = user.id
    let edgeId = node.id + nodeId

    await appRef.executeCommand<NsNodeCmd.AddNode.IArgs>(XFlowNodeCommands.ADD_NODE.id, {
      nodeConfig: {
        id: nodeId,
        x: node.getData().x + 180,
        y: node.getData().y,
        width: 150,
        height: 40,
        label: user.username
      },
    })
    await appRef.executeCommand<NsEdgeCmd.AddEdge.IArgs>(XFlowEdgeCommands.ADD_EDGE.id, {
      edgeConfig: {
        id: edgeId, source: node.id, target: nodeId
      }
    })

    let data = await appRef.getAllEdges()
    let result = [];
    let lastId = "root"
    let stop = true
    // @ts-ignore
    do {
      stop = true
      data.forEach(item=>{
        if(item.getSource().cell == lastId) {
          result.push({sourceUserId: item.getSource().cell == "root" ? 0 : item.getSource().cell, userId: item.getTarget().cell})
          lastId = item.getTarget().cell
          stop = false;
        }
      })
    } while(!stop)
    onNodeChange(result)
  }

  const onOk = (user) => {
    setState({...state, isModalVisible: false})
    const {adminUserIds, userOptions, node} = user;
    console.log(userOptions)
    adminUserIds.forEach(uid => {
      userOptions.forEach(item=>{
        if(item.id == uid) {
          onCreateNode(node, item)
        }
      })
    })
  }
  const onCancel = ()=>{
    setState({...state, isModalVisible: false})
  }

  const onAddNode = (node) => {
    setState({...state, isModalVisible: true, currentNode: node, isDisplay: false})
  }

  const onDelNode = (node) => {
    setState({...state, isDisplay: false})
    appRef.executeCommand<NsNodeCmd.DelNode.IArgs>(XFlowNodeCommands.DEL_NODE.id, {
      nodeConfig: node.getData()
    })
  }

  const onConsoleMenu = () => {
    setState({...state, isDisplay: false, currentUser:{adminUserIds:''}})
  }

  useEffect(() =>{

  })


  // @ts-ignore
  return (

        <XFlow
          className="xflow-graph-zoom-demo"
          graphData={graphData}
          graphLayout={{
            layoutType: 'dagre',
            layoutOptions: {
              type: 'dagre',
              rankdir: 'TB',
              nodesep: 60,
              ranksep: 40,
            },
          }}
          onLoad={onLoad}
        >
          <UserModal userOptions={userOptions} currentNode={state.currentNode} isModalVisible={state.isModalVisible} item={state.currentUser} onOk={onOk} onCancel={onCancel} />
          <NodeContextMenu isDisplay={state.isDisplay} experimentId={"root1"} node={state.currentNode} appRef={state.appRef} onAddNode={onAddNode} onDelNode={onDelNode} onConsoleMenu={onConsoleMenu} />

          <XFlowCanvas config={useGraphConfig()} />
        </XFlow>
  )
}

export default ApprovalProcessDag
